package com.kfyang.manualgear.generator.declare;

import com.kfyang.manualgear.constant.Constants;
import com.kfyang.manualgear.util.GlobalConfig;
import com.kfyang.manualgear.util.GlobalConfigUtils;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.kfyang.manualgear.constant.TypeNameConstants;
import com.kfyang.manualgear.struct.MethodInfo;
import org.yaml.snakeyaml.LoaderOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.Constructor;

import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.tools.FileObject;
import javax.tools.StandardLocation;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.kfyang.manualgear.util.GlobalConfigUtils.elementUtils;

/**
 * 类生成工具类
 */
public abstract class ClassSpecGenerator {
    protected TypeSpec.Builder classBuilder;

    private final Element element;


    public ClassSpecGenerator(Element element) {
        this.element = element;
    }

    public ClassWrapper create() {
        init();
        addRepository();
        implementInterface();
        addExecuteEngine();
        ClassWrapper classWrapper = new ClassWrapper(classBuilder);
        initMethodInfoMap(classWrapper);
        return classWrapper;
    }

    /**
     * 实现源接口
     */
    void implementInterface() {
        classBuilder.addSuperinterface(TypeName.get(element.asType()));
    }

    /**
     * 初始化类构造器
     */
    void init() {
        classBuilder = TypeSpec.classBuilder(daoName())
            .addModifiers(Modifier.PUBLIC);
    }

    /**
     * 实现类名
     * @return 实现类名
     */
    private String daoName() {
        return element.getSimpleName().toString() + Constants.IMPL;
    }

    /**
     * 添加 Repository 注解
     */
    void addRepository() {
        classBuilder.addAnnotation(TypeNameConstants.REPOSITORY_TYPE);
    }

    /**
     * 添加执行引擎
     */
    abstract protected void addExecuteEngine();

    /**
     * 读取Mapper文件
     */
    protected void initMethodInfoMap(ClassWrapper classWrapper) {
        String fullClassName = elementUtils.getPackageOf(element).getQualifiedName().toString() + "." + element.getSimpleName().toString();

        List<MethodInfo> methodInfos = GlobalConfigUtils.methodInfoMap.get(fullClassName);
        if (methodInfos == null) return;

        // 全局frag
        MethodInfo globalInfo = methodInfos.get(0);
        Map<String, MethodInfo.Frag> globalFragMap = new HashMap<>();
        if (globalInfo.frags != null) {
            for (MethodInfo.Frag frag : globalInfo.frags) {
                globalFragMap.put(frag.id, frag);
            }
        }
        classWrapper.globalFragMap = globalFragMap;

        Map<String, MethodInfo> methodInfoMap = new HashMap<>();
        for (int i = 1; i < methodInfos.size(); i++) {
            MethodInfo methodInfo = methodInfos.get(i);
            if (methodInfo.methodName != null && !methodInfo.methodName.isBlank()) {
                methodInfoMap.put(methodInfo.methodName, methodInfo);
            }
        }
        classWrapper.methodInfoMap = methodInfoMap;
    }
}
